{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 作业二\n",
    "###  要求：为MNIST数据集构建一个分类器，并在测试集上达成超过90%的精度 。提示：KNeighborsClassiﬁer对这个任务非常有效"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. 导入数据集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.datasets import fetch_mldata\n",
    "# 读取本地数据集内容\n",
    "mnist = fetch_mldata('mnist-original', data_home='./')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 标签和训练数据\n",
    "X, y = mnist['data'], mnist['target']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 建立测试集\n",
    "X_train, X_test, y_train, y_test = X[:60000,:], X[60000:,:], y[:60000], y[60000:]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  2. 划分训练集、测试集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import sklearn\n",
    "import matplotlib.pyplot as plt\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 有些模型对排队序号敏感，故将训练集洗牌打乱赋值\n",
    "shuffle_index = np.random.permutation(60000)\n",
    "X_train, y_train = X_train[shuffle_index], y_train[shuffle_index]\n",
    "\n",
    "# 测试集洗牌赋值\n",
    "shuffle_index = np.random.permutation(10000)\n",
    "X_test, y_test = X_test[shuffle_index], y_test[shuffle_index]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. 选择标签"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "some_digit = X_train[23456]\n",
    "some_digit_img = some_digit.reshape(28, 28)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib\n",
    "%matplotlib inline\n",
    "plt.imshow(some_digit_img, cmap = matplotlib.cm.binary)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. 选择模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "# 多标签分类  拿出“6”的标签\n",
    "y_train_6 = (y_train == 6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',\n",
       "           metric_params=None, n_jobs=1, n_neighbors=5, p=2,\n",
       "           weights='uniform')"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 计算距离\n",
    "kn_clf = KNeighborsClassifier()\n",
    "kn_clf.fit(X_train, y_train_6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "some_digit = X_train[23456]\n",
    "some_digit = [some_digit]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([False])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 测试指定数据\n",
    "kn_clf.predict(some_digit)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. 精度和召回"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Fitting 5 folds for each of 6 candidates, totalling 30 fits\n"
     ]
    }
   ],
   "source": [
    "from sklearn.model_selection import GridSearchCV\n",
    "\n",
    "param_grid = [{'weights': [\"uniform\", \"distance\"], 'n_neighbors': [3, 4, 5]}]\n",
    "\n",
    "knn_clf = KNeighborsClassifier()\n",
    "grid_search = GridSearchCV(knn_clf, param_grid, cv = 5, verbose = 3, n_jobs = -1)\n",
    "grid_search.fit(X_train, y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "grid_search.best_params_\n",
    "grid_search.best_score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "y_pred = grid_search.predict(X_test)\n",
    "accuracy_score(y_test, y_pred)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
